using Mono.Cecil;
using Mono.Cecil.Cil;

namespace Cil.Ast;

public sealed class ArrayLengthExpression : SingleInstructionExpression
{
	public const int ArrayPos = 0;
	public const int MaxNodes = 1;

	public ArrayLengthExpression(Context context, Instruction position, TypeReference itemType, Expression array) 
		: base(context, position)
	{
		if(!(array.ReturnType is ArrayType)) 
		{
			throw new ArgumentException($"{nameof(array)} is not array ({array.ReturnType})");
		}

		// setup parents
		array.ParentNode = this;

		// base class
		ReadsStack = 1;
		WritesStack = 1;
		ReturnType = context.MakeRef<int>();
		Nodes = new FixedList<Expression>(MaxNodes);

		// this
		ItemType = itemType;
		ArrayExpression = array;
	}

	public TypeReference ItemType { get; private set; }

	public Expression ArrayExpression { get { return Nodes[ArrayPos]; } set { Nodes[ArrayPos] = value; value.ParentNode = this; } }

	public override string ToString()
	{
		return string.Format("{0}.Length", ArrayExpression);
	}
}

public static partial class IlAst
{
	public static ArrayLengthExpression ArrayLength(Context context, Instruction position, TypeReference itemType, Expression exp_array)
	{
		return new ArrayLengthExpression(context, position, itemType, exp_array);
	}
}